package com.love.marriage.TecentIm.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.love.marriage.TecentIm.config.LocalImConfig;
import com.love.marriage.TecentIm.service.ChatService;
import com.love.marriage.TecentIm.service.TencentImService;
import com.love.marriage.TecentIm.service.WuKongImService;
import com.love.marriage.TecentIm.vo.*;
import com.love.marriage.common.enums.DefaultAmountTypeEnum;
import com.love.marriage.common.enums.ResultEnum;
import com.love.marriage.common.enums.TransactionType;
import com.love.marriage.common.exceptions.SystemException;
import com.love.marriage.config.DefaultAmountConfig;
import com.love.marriage.defaultAmountConfig.service.DefaultAmountConfigService;
import com.love.marriage.defaultAmountConfig.vo.DefaultAmountConfigVo;
import com.love.marriage.userBalanceInfo.service.UserBalanceInfoService;
import com.love.marriage.userBalanceInfo.vo.UserBalanceInfoAddVo;
import com.love.marriage.userBalanceInfo.vo.UserBalanceInfoVo;
import com.love.marriage.userBehaviorInfo.service.UserBehaviorInfoService;
import com.love.marriage.userBehaviorInfo.vo.UserBehaviorInfoVo;
import com.love.marriage.userChatInfo.service.UserChatInfoService;
import com.love.marriage.userChatInfo.vo.UserChatInfoVo;
import com.love.marriage.userInfo.mapper.UserInfoMapper;
import com.love.marriage.userInfo.service.UserInfoService;
import com.love.marriage.userInfo.vo.MemberAboutVo;
import com.love.marriage.userInfo.vo.UserInfoVo;
import com.love.marriage.userInfo.vo.UserVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class ChatServiceImpl implements ChatService {

    private final TencentImService tencentImService;

    private final UserChatInfoService userChatInfoService;

    private final UserInfoService userInfoService;

    private final DefaultAmountConfig defaultAmountConfig;

    private final UserBalanceInfoService userBalanceInfoService;

    private final UserBehaviorInfoService userBehaviorInfoService;

    private final DefaultAmountConfigService defaultAmountConfigService;

    //    private final LocalImService localImService;
    private final WuKongImService wuKongImService;

    private final LocalImConfig localImConfig;

    private final UserInfoMapper userInfoMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String sendMessage(Long fromUser, Long toUser, String message) throws Exception {
        //  查询两个用户在聊天中是否存在
        //  如果不存在则创建一个会话
        // 如果不存在则需要查询用户信息，然后将头像信息、昵称创建用户
        // 然后判断当前用户是否是会员，如果是会员直接发送消息，如果不是会员，则需要计数发消息，或者扣余额发消息
        judge(fromUser, true);
        judge(toUser, false);
        // 保存聊天行为到用户行为表中
        UserBehaviorInfoVo userBehaviorInfoVo = new UserBehaviorInfoVo();
        userBehaviorInfoVo.setActionType("chat");
        userBehaviorInfoVo.setUserId(fromUser);
        userBehaviorInfoVo.setActorId(toUser);
        UserInfoVo fromUserVo = userInfoService.queryUserInfo(fromUser);
        UserInfoVo toUserVo = userInfoService.queryUserInfo(toUser);
        userBehaviorInfoService.addUserBehaviorInfo(userBehaviorInfoVo);
        Long messageId = wuKongImService.sendMessage(fromUserVo.getLocalImId(), toUserVo.getLocalImId(), message);
        // 更新消息未读数量为0
        CompletableFuture.runAsync(() -> {
            try {
                wuKongImService.setConversationUnread(fromUserVo.getLocalImId(), toUserVo.getLocalImId(), 1, 0);
            } catch (Exception e) {
                log.error("Failed to set conversation unread count", e);
            }
        });
        return messageId == null ? null : messageId.toString();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String sendMessageMoney(Long fromUser, Long toUser, String message) throws Exception {
        //  查询两个用户在聊天中是否存在
        //  如果不存在则创建一个会话
        // 如果不存在则需要查询用户信息，然后将头像信息、昵称创建用户
        // 然后判断当前用户是否是会员，如果是会员直接发送消息，如果不是会员，则需要计数发消息，或者扣余额发消息
        // 保存聊天行为到用户行为表中
        UserBehaviorInfoVo userBehaviorInfoVo = new UserBehaviorInfoVo();
        userBehaviorInfoVo.setActionType("chat");
        userBehaviorInfoVo.setUserId(fromUser);
        userBehaviorInfoVo.setActorId(toUser);
        UserInfoVo userInfoVo = userInfoService.queryUserInfo(toUser);
        UserInfoVo fromUserVo = userInfoService.queryUserInfo(fromUser);
        userBehaviorInfoService.addUserBehaviorInfo(userBehaviorInfoVo);
        Long messageId = wuKongImService.sendMessage(fromUserVo.getLocalImId(), userInfoVo.getLocalImId(), message);
        // 更新消息未读数量为0
        CompletableFuture.runAsync(() -> {
            try {
                wuKongImService.setConversationUnread(fromUserVo.getLocalImId(), userInfoVo.getLocalImId(), 1, 0);
            } catch (Exception e) {
                log.error("Failed to set conversation unread count", e);
            }
        });
        return messageId == null ? null : messageId.toString();
    }

    @Override
    public String withdrawMessage(String fromAccount, String toAccount, String msgKey) throws Exception {
        return tencentImService.withdrawMessage(fromAccount, toAccount, msgKey);
    }

    @Override
    public Boolean sendReadReceipt(Long fromUser, Long toUser, List<ChatReadInfoVo> chatReadInfoVoList) throws Exception {
        tencentImService.sendReadReceipt(fromUser.toString(), toUser.toString(), chatReadInfoVoList);
        return true;
    }

    private void judge(Long userId, boolean saveChat) throws Exception {
        UserChatInfoVo dbUserChatInfoVo = userChatInfoService.queryUserChatInfoByUserId(userId, DefaultAmountTypeEnum.CHAT_COUNT.getCode());
        UserVo userVo = userInfoService.queryUser(userId);

        // Handle case when user chat info doesn't exist
        if (dbUserChatInfoVo == null) {
            handleNewUserChatInfo(userId, userVo, saveChat);
            return;
        }

        // If we don't need to save chat, we're done
        if (!saveChat) {
            return;
        }

        // Handle existing user chat info
        handleExistingUserChatInfo(userId, dbUserChatInfoVo);
    }

    private void handleNewUserChatInfo(Long userId, UserVo userVo, boolean saveChat) throws Exception {
        // 创建一个新的
        if (userVo == null) {
            throw new SystemException(ResultEnum.USER_NOT_EXIST);
        }

        // 在im中创建用户信息
        if (userVo.getLocalImId() == null) {
            // 如果localImId为空时，表示未在悟空im中注册
            wuKongImService.loginOrRegister(userId.toString());
        }

        if (saveChat) {
            DefaultAmountConfigVo chatMessageConfig = defaultAmountConfigService.queryDefaultAmountConfigByCode(DefaultAmountTypeEnum.CHAT_COUNT.getCode());
            UserChatInfoVo userChatInfoVo = new UserChatInfoVo();
            userChatInfoVo.setUserId(userId);
            // 检查用户是否为会员、红娘或单身合伙人，如果是则聊天免费
            int add = 1;
            if (isUserEligibleForFreeChat(userId)) {
                add = 0;
            }
            userChatInfoVo.setType(DefaultAmountTypeEnum.CHAT_COUNT.getCode());
            userChatInfoVo.setChatCount(chatMessageConfig.getAmount().intValue() - add);
            userChatInfoService.addUserChatInfo(userChatInfoVo);
        }
    }

    private void handleExistingUserChatInfo(Long userId, UserChatInfoVo dbUserChatInfoVo) throws Exception {
        // 如果当前聊天数量大于限制数量，则消耗余额
        DefaultAmountConfigVo chatConfig = defaultAmountConfigService.queryDefaultAmountConfigByCode(DefaultAmountTypeEnum.CHAT.getCode());
        BigDecimal chatAmount = (chatConfig != null) ? chatConfig.getAmount() : defaultAmountConfig.getChatMessage();

        // 检查用户是否为会员、红娘或单身合伙人，如果是则聊天免费
        if (isUserEligibleForFreeChat(userId)) {
            chatAmount = BigDecimal.ZERO;
        }

        if (chatAmount.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }

        if (dbUserChatInfoVo.getChatCount() <= 0) {
            // 如果报名金额不为空则使用报名金额，否则查看默认配置表中是否有值，最后查询配置表中配置金额
            UserBalanceInfoVo userBalanceInfoVo = userBalanceInfoService.queryUserBalanceInfoByUserId(userId);

            // Check if user has enough balance
            boolean hasValidChatAmount = BigDecimal.ZERO.compareTo(chatAmount) < 0;
            boolean hasInsufficientBalance = userBalanceInfoVo == null || userBalanceInfoVo.getBalance().compareTo(chatAmount) < 0;

            if (hasValidChatAmount && hasInsufficientBalance) {
                throw new SystemException(ResultEnum.USER_NO_ENOUGH_BALANCE);
            }

            UserBalanceInfoAddVo userBalanceInfoAddVo = new UserBalanceInfoAddVo();
            userBalanceInfoAddVo.setUserId(userId);
            userBalanceInfoAddVo.setAmount(chatAmount);

            // 这里单独开启事务处理余额扣减
            userBalanceInfoService.reduceAmount(userBalanceInfoAddVo, dbUserChatInfoVo.getId(), TransactionType.CHAT.getCode(), "聊天");
        }

        UserChatInfoVo updateInfo = new UserChatInfoVo();
        BeanUtils.copyProperties(dbUserChatInfoVo, updateInfo);
        updateInfo.setChatCount(updateInfo.getChatCount() - 1);
        userChatInfoService.updateUserChatInfo(updateInfo);
    }

    /**
     * 检查用户是否符合免费聊天条件（会员、红娘或单身合伙人）
     *
     * @param userId 用户ID
     * @return 是否符合免费聊天条件
     */
    private boolean isUserEligibleForFreeChat(Long userId) {
        try {
            List<MemberAboutVo> userMemberInfoList = userInfoMapper.getMemberAboutList(userId);
            if (userMemberInfoList == null || userMemberInfoList.isEmpty()) {
                return false;
            }

            for (MemberAboutVo memberAboutVo : userMemberInfoList) {
                // 检查是否为会员
                if (memberAboutVo.getMembershipFlag() != null && memberAboutVo.getMembershipFlag()) {
                    return true;
                }

                // 检查是否为红娘
                if (memberAboutVo.getMatchmakerFlag() != null && memberAboutVo.getMatchmakerFlag()) {
                    return true;
                }

                // 检查是否为单身合伙人
                if (memberAboutVo.getPartnerFlag() != null && memberAboutVo.getPartnerFlag() &&
                        memberAboutVo.getOfflineServiceProviderVo() != null &&
                        memberAboutVo.getOfflineServiceProviderVo().getSingleFlag() != null &&
                        memberAboutVo.getOfflineServiceProviderVo().getSingleFlag()) {
                    return true;
                }
            }
        } catch (Exception e) {
            log.error("检查用户免费聊天资格时出错: {}", e.getMessage(), e);
        }

        return false;
    }

    /**
     * @param operatorUserId
     * @param peerUserId
     * @param maxCnt
     * @param lastMsgKey
     * @description: 获取聊天记录信息
     * @author: alex
     * @return: com.love.marriage.TecentIm.vo.CharEachHistoryVo
     */
    @Override
    public ChatEachHistoryVo getChatHistory(Long operatorUserId, Long peerUserId, int maxCnt, long maxTime, String lastMsgKey) throws Exception {
        String chatHistory = tencentImService.getChatHistory(operatorUserId.toString(), peerUserId.toString(), 0, maxTime, maxCnt, lastMsgKey);
        UserVo operator = userInfoService.queryUser(operatorUserId);
        UserVo peer = userInfoService.queryUser(peerUserId);
        ChatEachHistoryVo chatEachHistoryVo = new ChatEachHistoryVo();
        chatEachHistoryVo.setOperatorUserId(operatorUserId);
        chatEachHistoryVo.setPeerUserId(peerUserId);
        chatEachHistoryVo.setOperatorUser(operator);
        chatEachHistoryVo.setPeerUser(peer);
        chatEachHistoryVo.setMessage(chatHistory);
        return chatEachHistoryVo;
    }

    @Override
    public ChatListInfoVo getRecentContacts(RecentContactRequest request) throws Exception {
        String recentContacts = tencentImService.getRecentContacts(request);
        JSONObject jsonObject = JSONObject.parseObject(recentContacts);
        ChatListInfoVo chatListInfoVo = new ChatListInfoVo();
        chatListInfoVo.setStartIndex(jsonObject.getInteger("StartIndex"));
        chatListInfoVo.setTimeStamp(jsonObject.getInteger("TimeStamp"));
        chatListInfoVo.setCompleteFlag(jsonObject.getString("CompleteFlag"));
        if (jsonObject.getString("SessionItem") != null) {
            List<ChatListVo> res = new ArrayList<>();
            List<JSONObject> list = JSONObject.parseObject(jsonObject.getString("SessionItem"), List.class);
            Set<String> peerUserId = new HashSet<>();
            if (list != null && list.size() > 0) {
                for (JSONObject json : list) {
                    ChatListVo chatListVo = new ChatListVo();
                    chatListVo.setPeerUserId(json.getLong("To_Account"));
                    chatListVo.setMsgTime(json.getString("MsgTime"));
                    chatListVo.setTopFlag(json.getString("TopFlag"));
                    peerUserId.add(json.getString("To_Account"));
                    res.add(chatListVo);
                }
                Map<String, Object> batchUnreadMessageCount = tencentImService.getBatchUnreadMessageCount(request.getFrom_Account(), peerUserId.toArray(new String[0]));
                log.info("batchUnreadMessageCount:{}", batchUnreadMessageCount);

                // 将 batchUnreadMessageCount 转换为 JSON 字符串
                ObjectMapper objectMapper = new ObjectMapper();
                String jsonString = objectMapper.writeValueAsString(batchUnreadMessageCount);

                // 将 JSON 字符串转换为 JsonNode
                JsonNode rootNode = objectMapper.readTree(jsonString);

                // 获取 C2CUnreadMsgNumList 节点
                JsonNode unreadMsgNumListNode = rootNode.get("C2CUnreadMsgNumList");

                // 创建 Map 来存储结果
                Map<String, Integer> resultMap = new HashMap<>();

                // 遍历 C2CUnreadMsgNumList 数组
                if (unreadMsgNumListNode != null && unreadMsgNumListNode.isArray()) {
                    for (JsonNode node : unreadMsgNumListNode) {
                        String peerAccount = node.get("Peer_Account").asText();
                        int unreadMsgNum = node.get("C2CUnreadMsgNum").asInt();
                        resultMap.put(peerAccount, unreadMsgNum);
                    }
                }

                // 打印或返回 resultMap
                log.info("Unread message count per peer: {}", resultMap);
                res.forEach(chatListVo -> {
                    try {
                        chatListVo.setUserVo(userInfoService.queryUser(chatListVo.getPeerUserId()));
                        ChatEachHistoryVo chatHistory = getChatHistory(Long.parseLong(request.getFrom_Account()), chatListVo.getPeerUserId(), 1, Long.parseLong(chatListVo.getMsgTime()), null);
                        chatListVo.setMessageInfo(chatHistory.getMessage());
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    chatListVo.setUnreadCount(resultMap.get(chatListVo.getPeerUserId().toString()));
                });
                chatListInfoVo.setChatList(res);
            }
        }
        return chatListInfoVo;
    }

    @Override
    public Boolean deleteChatMessages(Long fromUser, Long toUser, List<String> msgKeyList) throws Exception {
        if (msgKeyList == null || msgKeyList.isEmpty()) {
            throw new Exception("msgKeyList is empty");
        }
        return tencentImService.deleteChatMessages(fromUser.toString(), toUser.toString(), msgKeyList);
    }

    @Override
    public String generateUserSig(Long userId) throws Exception {
        addNewUser(userId);
        return tencentImService.generateUserSig(String.valueOf(userId));
    }

    @Override
    public Boolean addNewUser(Long userId) throws Exception {
        log.info("添加用户到im");
        UserChatInfoVo dbUserChatInfoVo = userChatInfoService.queryUserChatInfoByUserId(userId, DefaultAmountTypeEnum.CHAT_COUNT.getCode());
        UserVo userVo = userInfoService.queryUser(userId);
        if (userVo.getLocalImId() == null) {
            // 2025/1/12 导入本地im
            String userIdStr = userId.toString();
            wuKongImService.loginOrRegister(userIdStr);
            // 2025/1/12 保存im中id到用户表
            UserInfoVo userInfoVo = userInfoService.queryUserInfo(userId);
            userInfoVo.setLocalImId(userIdStr);
            userInfoService.updateUserInfo(userInfoVo);
            if (dbUserChatInfoVo == null) {
                DefaultAmountConfigVo chatMessageConfig = defaultAmountConfigService.queryDefaultAmountConfigByCode(DefaultAmountTypeEnum.CHAT_COUNT.getCode());
                UserChatInfoVo userChatInfoVo = new UserChatInfoVo();
                userChatInfoVo.setUserId(userId);
                userChatInfoVo.setChatCount(chatMessageConfig.getAmount().intValue());
                userChatInfoVo.setType(DefaultAmountTypeEnum.CHAT_COUNT.getCode());
                userChatInfoService.addUserChatInfo(userChatInfoVo);
            }
        }
        return true;
    }

    @Override
    public List<LocalImChatListVo> getLocalImChatList(Long userId, String page, String limit) throws Exception {
        List<LocalImChatListVo> localImChatList = wuKongImService.getImChatList(userId.toString(),
                page != null ? Long.parseLong(page) : null,
                limit == null ? null : Integer.parseInt(limit));
        if (localImChatList == null || localImChatList.isEmpty()) {
            return null;
        }
        UserVo userVo = userInfoService.queryUser(userId);
        return localImChatList.parallelStream().peek(item -> {
            item.setUserInfo(userVo);
            try {
                item.setToUserInfo(userInfoService.queryByLocalImId(item.getToUid()));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }).collect(Collectors.toList());
    }

    @Override
    public LocalImChatHistoryVo getLocalImChatHistory(Long userId, Long toUserId, Long endMessageSeq, Integer limit) throws Exception {
        if (toUserId == null) {
            throw new SystemException("1200001", "接收人不能为空");
        }
        if (userId == null) {
            throw new SystemException("1200002", "发送人不能为空");
        }
        UserVo userVo = userInfoService.queryUser(userId);
        UserVo toUserInfoVo = userInfoService.queryUser(toUserId);
        List<Map<String, Object>> localImChatHistory = wuKongImService.getImChatHistory(userVo.getLocalImId(), toUserInfoVo.getLocalImId(), 1, null, endMessageSeq, limit);
        LocalImChatHistoryVo localImChatHistoryVo = new LocalImChatHistoryVo();
        localImChatHistoryVo.setHistoryList(localImChatHistory);
        localImChatHistoryVo.setToUserInfo(toUserInfoVo);
        UserVo userInfoVo = userInfoService.queryUser(toUserId);
        localImChatHistoryVo.setUserInfo(userInfoVo);
        // 更新消息未读数量为0
        CompletableFuture.runAsync(() -> {
            try {
                wuKongImService.setConversationUnread(userVo.getLocalImId(), toUserInfoVo.getLocalImId(), 1, 0);
            } catch (Exception e) {
                log.error("Failed to set conversation unread count", e);
            }
        });
        return localImChatHistoryVo;
    }
}
